﻿Imports System.Collections
Imports System.Net.Sockets
Imports System.Net

Public Class SocketListener

    Public Shared clients As IList = New Collections.ArrayList
    Public Shared checkRead As IList = New Collections.ArrayList
    Public Shared checkError As IList = New Collections.ArrayList
    Public Shared numClients As Integer = 0
    Public Shared listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

    Public Shared Sub start()
        Try
            listener.Bind(New IPEndPoint(IPAddress.Parse(Config.WorldServerIP), Config.WorldServerPort))
            listener.Listen(100)
            listener.Blocking = False
            log.log(LogType.MSG_INFO, "Server listening on port " & String.Concat(Config.WorldServerPort))
        Catch
        End Try
        Dim listenThread As New Threading.Thread(AddressOf SocketListener.listenThread)
        listenThread.Start()
    End Sub

    Public Shared Sub listenThread()
        Do While True
            Try
                checkRead.Clear()
                checkError.Clear()
                For Each obj As Object In clients
                    Dim handler As Handler = obj
                    checkRead.Add(handler.workSocket)
                    checkError.Add(handler.workSocket)
                Next
                checkRead.Add(listener)
                checkError.Add(listener)
                Socket.Select(checkRead, Nothing, checkError, 1000)
                For Each obj As Object In clients
                    Dim handler As Handler = obj
                    If (checkRead.Contains(handler.workSocket)) Then
                        If (handler.handle() <> True) Then
                            log.log(LogType.MSG_INFO, "User Disconnected from IP: " & String.Concat(IPAddress.Parse(CType(handler.workSocket.RemoteEndPoint, IPEndPoint).Address.ToString())))
                            handler.workSocket.Close()
                            clients.Remove(handler)
                            numClients -= 1
                            Continue Do
                        End If
                    End If
                    If (checkError.Contains(handler.workSocket)) Then
                        log.log(LogType.MSG_INFO, "User Disconnected from IP: " & String.Concat(IPAddress.Parse(CType(handler.workSocket.RemoteEndPoint, IPEndPoint).Address.ToString())))
                        handler.workSocket.Close()
                        clients.Remove(handler)
                        numClients -= 1
                        Continue Do
                    End If
                Next

                If (checkRead.Contains(listener)) Then
                    If (handle(listener) <> True) Then
                        log.log(LogType.MSG_ERROR, "Error in checkRead.")
                        listener.Close()
                        Exit Do
                    End If
                End If
                If (checkError.Contains(listener)) Then
                    log.log(LogType.MSG_ERROR, "Error in checkError.")
                    listener.Close()
                    Exit Do
                End If
            Catch
            End Try
        Loop
    End Sub

    Public Shared Function handle(ByVal socket As Socket) As Boolean
        Try
            Dim client As Socket = socket.Accept()
            Dim handler As New Handler(client)
            clients.Add(handler)
            checkRead.Add(client)
            checkError.Add(client)
            numClients += 1
            log.log(LogType.MSG_INFO, "User Connected from IP: " & String.Concat(IPAddress.Parse(CType(handler.workSocket.RemoteEndPoint, IPEndPoint).Address.ToString())))
            Return True
        Catch ex As SocketException
        End Try
    End Function

End Class